package rt2

import (
	"errors"
	"fmt"
	"sync"

	"gitee.com/zhang-li17/rt2/pcol"

	"gitee.com/copperxcx/hb"
	"gitee.com/copperxcx/res"
	"google.golang.org/protobuf/proto"
)

type TypeResDecoder func(mgr *res.ResManager, r *pcol.Res) error

// 从pcol.Res设置、获取值的函数
type setResFunc[T res.ScalarType] func(*pcol.Res, T)
type getResFunc[T res.ScalarType] func(*pcol.Res) T
type resTypeDecoderFunc[T res.ScalarType] struct {
	resType pcol.ResourceType
	fset    setResFunc[T]
	fget    getResFunc[T]
}

type ClientHandler struct {
	recvDec *UdpRecvDecoder
	client  *MultiCastClient
	mgr     *res.ResManager

	mu         sync.Mutex
	resDecoder map[pcol.ResourceType]TypeResDecoder

	resTypeFuncMap map[pcol.ResourceType]any

	resMap map[string]*pcol.Res

	heartbeat *hb.Detector

	resReqMissionManager *ResReqMissionManager
}

func (c *ClientHandler) Name() string {
	return c.client.Name
}

func (c *ClientHandler) IsAlive() bool {
	return c.heartbeat.IsAlive()
}

func (c *ClientHandler) GetAllRes() (ret []*pcol.Res) {
	for _, v := range c.resMap {
		ret = append(ret, v)
	}
	return
}

func HandlerGetRes[T res.ScalarType](c *ClientHandler, name string) (t T, err error) {
	if r, ok := c.resMap[name]; ok {

		if t1, ok := c.resTypeFuncMap[r.GetResType()]; ok {
			tt, ok := t1.(resTypeDecoderFunc[T])
			if ok {
				return tt.fget(r), nil
			}
			err = fmt.Errorf("resource type %#v not registered", r.GetResType())
		} else {
			err = fmt.Errorf("resource type %#v not registered", r.GetResType())
		}
	} else {
		err = fmt.Errorf("resource %s not found", name)
	}
	return
}

func HandlerSetRes[T res.ScalarType](c *ClientHandler, name string, t T) (err error) {
	if r := res.GetWritableScalar[T](c.mgr, name); r != nil {
		return r.SetValue(t)
	}
	return fmt.Errorf("resource %s not found", name)
}

// clientIsServerSide: false表示连接的对象是客户端
func NewClientHandler(c *MultiCastClient, clientIsServerSide bool) *ClientHandler {
	dec := NewRecvDecoder(c.Conn, c.Dec)

	handler := &ClientHandler{
		resDecoder:           make(map[pcol.ResourceType]TypeResDecoder), // ← 加
		resTypeFuncMap:       make(map[pcol.ResourceType]any),
		resMap:               make(map[string]*pcol.Res),
		recvDec:              dec,
		client:               c,
		mgr:                  res.NewResManager(),
		heartbeat:            hb.NewDetector(c.Name, 1000, 3),
		resReqMissionManager: NewResReqMissionManager(),
	}
	// 注册可解析的类型
	handler.registerDecodeTypes()

	// 初始化回调解析函数等
	if clientIsServerSide {
		handler.initServer()
	} else {
		handler.initClient()
	}

	// 处理心跳
	go func() {
		ch := handler.recvDec.Start(handler.recvDec.Conn.RemoteAddr().String())
		for range ch {
			handler.heartbeat.Heartbeat()
		}
	}()
	return handler
}

func (c *ClientHandler) initServer() {
	c.registerServerCallbacks()
}

func (c *ClientHandler) initClient() {
	c.registerClientCallbacks()
	go func() {
		ch := c.resReqMissionManager.Start()
		for d := range ch {
			// fmt.Println(" replyResValResponse, data!!!")
			c.replyResValResponse(d)
		}
	}()
}

func (c *ClientHandler) SendMessage(msgType pcol.MessageType, msg proto.Message, seq int32) error {
	return SendProtoMsgWithSeq(c.client, pcol.MessageType_RES_VAL_RESPONSE, msg, seq)
}

func (c *ClientHandler) replyResValResponse(d *ResReqMissionData) {
	rep := pcol.ResValResponse{
		Ok:            true,
		GroupId:       d.groupId,
		Interval:      d.intv,
		ReplyTimes:    d.replyTimes,
		MaxReplyTimes: d.totalReplyTimes,
		Res:           make([]*pcol.Res, len(d.names)),
	}
	if len(d.names) > 0 {
		for i, n := range d.names {
			rep.Res[i] = c.resMap[n]
		}
	} else {
		rep.Res = c.GetAllRes()
	}

	SendProtoMsgWithSeq(c.client, pcol.MessageType_RES_VAL_RESPONSE, &rep, d.seq)
}

func (c *ClientHandler) registerDecodeTypes() {

	registerDecodeResTypeWithFunc(c, pcol.ResourceType_BOOL, func(r *pcol.Res) bool { return r.BoolVal }, func(r *pcol.Res, val bool) { r.BoolVal = val })
	registerDecodeResTypeWithFunc(c, pcol.ResourceType_INT, func(r *pcol.Res) int32 { return r.IntVal }, func(r *pcol.Res, val int32) { r.IntVal = val })
	registerDecodeResTypeWithFunc(c, pcol.ResourceType_DOUBLE, func(r *pcol.Res) float64 { return r.DoubleVal }, func(r *pcol.Res, val float64) { r.DoubleVal = val })
	registerDecodeResTypeWithFunc(c, pcol.ResourceType_STRING, func(r *pcol.Res) string { return r.StringVal }, func(r *pcol.Res, val string) { r.StringVal = val })

	registerDecodeResTypeWithFunc(c, pcol.ResourceType_BOOL_ARRAY, func(r *pcol.Res) []bool { return r.BoolArrayVal.Val }, func(r *pcol.Res, val []bool) { r.BoolArrayVal = &pcol.BoolArray{Val: val} })
	registerDecodeResTypeWithFunc(c, pcol.ResourceType_INT_ARRAY, func(r *pcol.Res) []int32 { return r.IntArrayVal.Val }, func(r *pcol.Res, val []int32) { r.IntArrayVal = &pcol.IntArray{Val: val} })
	registerDecodeResTypeWithFunc(c, pcol.ResourceType_DOUBLE_ARRAY, func(r *pcol.Res) []float64 { return r.DoubleArrayVal.Val }, func(r *pcol.Res, val []float64) { r.DoubleArrayVal = &pcol.DoubleArray{Val: val} })
	registerDecodeResTypeWithFunc(c, pcol.ResourceType_STRING_ARRAY, func(r *pcol.Res) []string { return r.StringArrayVal.Val }, func(r *pcol.Res, val []string) { r.StringArrayVal = &pcol.StringArray{Val: val} })
	registerDecodeResTypeWithFunc(c, pcol.ResourceType_BINARY, func(r *pcol.Res) []byte { return r.BinaryVal }, func(r *pcol.Res, val []byte) { r.BinaryVal = val })

}

// 作为服务器，发送指令接收回令
func (c *ClientHandler) registerServerCallbacks() {
	// 服务器接收指令回复3类+事件通知1类
	c.recvDec.Dec.RegisterDecodeCallback(FrameType(pcol.MessageType_EVENT), func(f *Frame) (data any, err error) {
		evt := &pcol.Event{}
		err = proto.Unmarshal(f.Payload, evt)
		if err == nil {
			c.handleEvent(evt)
			data = evt
		}
		return
	})

	c.recvDec.Dec.RegisterDecodeCallback(FrameType(pcol.MessageType_RES_VAL_SET_RESPONSE), func(f *Frame) (data any, err error) {
		res := &pcol.ResValSetResponse{}
		err = proto.Unmarshal(f.Payload, res)
		if err == nil {
			c.handleResValSetResponse(f, res)
			data = res
		}
		return
	})

	c.recvDec.Dec.RegisterDecodeCallback(FrameType(pcol.MessageType_RES_VAL_RESPONSE), func(f *Frame) (data any, err error) {
		res := &pcol.ResValResponse{}
		err = proto.Unmarshal(f.Payload, res)
		if err == nil {
			c.handleResValResponse(res)
			data = res
		}
		return
	})

	c.recvDec.Dec.RegisterDecodeCallback(FrameType(pcol.MessageType_CANCEL_RES_VAL_RESPONSE), func(f *Frame) (data any, err error) {
		res := &pcol.ResValResponse{}
		err = proto.Unmarshal(f.Payload, res)
		if err == nil {
			c.handleCancelResValResponse(res)
			data = res
		}
		return
	})
}

// 作为客户端，接收指令，回复对应内容
func (c *ClientHandler) registerClientCallbacks() {
	// 客户端接收指令3类
	c.recvDec.Dec.RegisterDecodeCallback(FrameType(pcol.MessageType_RES_VAL_REQUEST), func(f *Frame) (data any, err error) {
		req := &pcol.ResValRequest{}
		err = proto.Unmarshal(f.Payload, req)
		if err == nil {

			fmt.Print("RegisterDecodeCallback\n")
			c.handleResValRequest(f, req)
			data = req
		}
		return
	})
	c.recvDec.Dec.RegisterDecodeCallback(FrameType(pcol.MessageType_CANCEL_RES_VAL_REQUEST), func(f *Frame) (data any, err error) {
		req := &pcol.ResValRequest{}

		err = proto.Unmarshal(f.Payload, req)
		if err == nil {

			c.handleCancelResValRequest(f, req)
			data = req
		}
		return
	})

	c.recvDec.Dec.RegisterDecodeCallback(FrameType(pcol.MessageType_RES_VAL_SET_REQUEST), func(f *Frame) (data any, err error) {
		req := &pcol.ResValSetRequest{}
		err = proto.Unmarshal(f.Payload, req)
		if err == nil {
			c.handleResValSetRequest(f, req)
			data = req
		}
		return
	})
}

func (c *ClientHandler) addOrUpdateRes(r *pcol.Res) error {
	dec, ok := c.resDecoder[r.GetResType()]
	if !ok {
		return errors.New("resource type not registered")
	}
	return dec(c.mgr, r)
}

func (c *ClientHandler) AddOrUpdateRes(r *pcol.Res) error {
	return c.addOrUpdateRes(r)
}
